<template>
  <!-- 复杂组件 -->
  <el-radio-group
    v-if="type == 'radio'"
    v-model="editValue"
    :size="size"
    style="line-height:40px;text-align: left;"
  >
    <el-radio v-for="item in options" :label="item.code" :key="item.code">{{
      item.title
    }}</el-radio>
  </el-radio-group>
  <el-checkbox-group
    v-else-if="type == 'check'"
    :size="size"
    v-model="editValue"
    style="text-align: left;"
  >
    <el-checkbox v-for="item in options" :label="item.code" :size="size" :key="item.code">{{
      item.title
    }}</el-checkbox>
  </el-checkbox-group>

  <el-cascader
    v-else-if="type == 'cascader'"
    :style="{ width: width }"
    :size="size"
    :options="tree"
    collapse-tags
    filterable
    :props="{
      multiple: multiple,
      expandTrigger: 'hover',
      checkStrictly: checkStrictly,
    }"
    v-model="list"
    clearable
    :placeholder="placeholder ? placeholder : '请搜索或选择'"
    @change="cascaderChange"
  />
  <el-autocomplete
    v-else-if="type == 'auto'"
    :size="size"
    v-model="editValue"
    :style="{ width: width }"
    :fetch-suggestions="querySearch"
    :placeholder="placeholder ? placeholder : '请输入内容'"
    :maxlength="maxlength ? maxlength : 4000"
    :minlength="minlength ? minlength : 0"
  ></el-autocomplete>
  <el-select
    v-else
    :style="{ width: width }"
    :size="size"
    :multiple="multiple"
    collapse-tags
    filterable
    v-model="editValue"
    clearable
    :placeholder="placeholder ? placeholder : '请搜索或选择'"
  >
    <el-option
      v-for="item in options"
      :key="item.code"
      :label="item.title"
      :value="item.code"
    >
      <span style="float: left">{{ item.title }}</span>
      <span style="float: right; color: #909399; margin-right:20px;">{{
        item.code
      }}</span>
    </el-option>
  </el-select>
</template>

<script>
const accept = {
  img: ".jpg, .jpeg, .png, .gif, .bmp, .JPG, .JPEG, .PNG, .GIF, .BMP",
  pdf: ".pdf .PDF",
  office: ".doc .docx .xls .xlsx .ppt .pptx .DOC .DOCX .XLS .XLSX .PPT .PPTX",
  all: "*",
};
export default {
  props: {
    //v-model绑定
    value: {
      type: [String, Number, Array, Boolean, Object],
      required: true,
    },
    //类型
    type: {
      type: String,
      validator: function(value) {
        return (
          ["radio", "check", "select", "cascader", "auto"].findIndex(
            (item) => item == value
          ) >= 0
        );
      },
    },
    //大小，支持'medium','small','mini',默认medium
    size: {
      type: String,
      validator: function(value) {
        return (
          ["medium", "small", "mini"].findIndex((item) => item == value) >= 0
        );
      },
      default: "medium",
    },
    width: { type: String, default: "100%" },
    //输入前提示语
    placeholder: String,
    //最大值，最小值，只有slider,number有效
    max: Number,
    min: Number,
    //原生属性，最大长度，最小长度
    maxlength: Number,
    minlength: Number,
    //字典名称，select,radio,check,cascader可用
    dictName: String,
    /**
     * TODO: (dictName) 需要建立一个缓存机制，每次去缓存中读取字典信息，如果缓存中没有，则自动去后台加载
     */
    //select,cascader是否可以多选，upload,img是否可以选择多个文件
    multiple: { type: Boolean, default: false },
    checkStrictly: { type: Boolean, default: false },
    //select,radio,check,cascader加载字典时的过滤条件，返回list
    filter: {
      type: Function,
      default: (list) => {
        return list;
      },
    },
    //auto组件的获取列表地址
    autoUrl: String,
    //auto组件获取列表的查询条件参数
    autoParams: { type: Object, default: () => {} },
  },
  data() {
    return {
      editValue: this.value,
      list: [],
      options: [],
      tree: [],
      acceptType: accept,
      restaurants: [],
      rule: "",
    };
  },
  methods: {
    querySearch(queryString, cb) {
      var restaurants = this.restaurants;
      var results = queryString
        ? restaurants.filter(this.createFilter(queryString))
        : restaurants;
      // 调用 callback 返回建议列表的数据
      cb(results);
    },
    createFilter(queryString) {
      return (restaurant) => {
        return (
          restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) ===
          0
        );
      };
    },
    cascaderChange(val) {
      if (typeof val != "undefined") {
        if (this.type == "cascader" && this.multiple) {
          let list = [];
          for (let i = 0; i < val.length; i++) {
            list.push(val[i].join(""));
          }
          this.editValue = list;
        } else if (this.type == "cascader" && !this.multiple) {
          this.editValue = val.join("");
        }
      }
    },
    splitCode(val) {
      if (typeof val != "undefined" && typeof this.role != "undefined") {
        const len = parseInt(this.role.split(":")[0]);
        const arr = this.role.split(":")[1].split("|");
        //变更级联选择器的传入值为el-cascader的标准格式
        let list = [];
        let start = 0;
        let end = len;
        for (let i = 0; i < arr.length; i++) {
          if (i > 0) {
            start += parseInt(arr[i - 1]);
          } else {
            start = 0;
          }
          end = start + parseInt(arr[i]);
          list.push(val.substring(start, end));
        }
        return list;
      }
    },
  },
  async created() {
    if (typeof this.dictName != "undefined") {
      if (this.type == "cascader") {
        const dict = await this.$dict.getTree(this.dictName);
        if (typeof dict != "undefined") {
          this.tree = dict.tree;
          this.role = dict.role;
          if (typeof this.value != "undefined") {
            if (this.multiple) {
              this.list = [];
              for (let i = 0; i < this.value.length; i++) {
                this.list.push(this.splitCode(this.value[i]));
              }
            } else {
              this.list = this.splitCode(this.value);
            }
          }
        }
      } else {
        this.options = this.filter(await this.$dict.getList(this.dictName));
      }
    }
    if (typeof this.autoUrl != "undefined") {
      const data = await this.$api.post(this.autoUrl, this.autoParams);
      const { success, result, code, msg } = data;
      if (success) {
        this.restaurants = result.rows;
      } else {
        this.$msg({
          message: `错误代码:${code},${msg}`,
          type: "warning",
        });
      }
    }
  },
  watch: {
    editValue(val) {
      this.$emit("input", val);
    },
    value(val) {
      this.editValue = val;
    },
  },
};
</script>
